package com.xxl.sso.server.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtils {

    @Autowired
    RedisTemplate redisTemplate;

    public Boolean hasKey(String key){
        return redisTemplate.hasKey(key);
    }

    //--------------------------string--------------------------------

    //setIfAbsent
    public Boolean setIfAbsent(String key,String value){
        return redisTemplate.boundValueOps(key).setIfAbsent(value);
    }

    public Boolean setIfAbsentExpire(String key,String value,Long time,TimeUnit timeUnit){
        return redisTemplate.boundValueOps(key).setIfAbsent(value,time, timeUnit);
    }

    public void set(String key,String value){
        redisTemplate.boundValueOps(key).set(value);
    }

    public String get(String key){
        String value=(String) redisTemplate.boundValueOps(key).get();
        return value;
    }

    //getAndSet 设置键的字符串值并返回其旧值
    public Object getAndSet(String key){
        return redisTemplate.boundValueOps(key).getAndSet("2");
    }

    //size 返回key所对应的value值得长度
    public Long sizeString(String key){
        return redisTemplate.boundValueOps(key).size();
    }


    //append 如果key已经存在并且是一个字符串，则该命令将该值追加到字符串的末尾。如果键不存在，则它被创建并设置为空字符串
    public void appendString(String key,String value){
        redisTemplate.boundValueOps(key).append(value);
    }

    /**
     * 注意：使用Jackson2JsonRedisSerializer序列化是无法使用increment()进行加减操作的，因为value在redis中的存储是String字符串类型，
     * 只有StringRedisSerializer、GenericToStringSerializer才可以使用，因为value在redis中的存储是数字类型的。
     * @param key
     * @param value
     * @return
     */
    public Long incrString(String key,Integer value){
        return redisTemplate.boundValueOps(key).increment(value);
    }


    //--------------------------List--------------------------------

    public void lpushAll(String key, String... values){
        redisTemplate.opsForList().leftPushAll(key,values);
    }

    public void lpushAll(String key, List values){
        redisTemplate.opsForList().leftPushAll(key,values);
    }

    public List range(String key){
        List values = redisTemplate.opsForList().range(key, 0, -1);

        //size 返回存储在键中的列表的长度。如果键不存在，则将其解释为空列表，并返回0。
        System.out.println("size: " + redisTemplate.opsForList().size(key));

        //V index(K key, long index); 根据下表获取列表中的值，下标是从0开始的
        System.out.println("index 2 member is: " + redisTemplate.opsForList().index(key,2));
        return values;
    }

    //void set(K key, long index, V value); 在列表中index的位置设置value值
    public void setIndexList(String key,Integer index,String value){
        redisTemplate.opsForList().set(key,index,value);
    }

    /**
     * Long remove(K key, long count, Object value);
     * 从存储在键中的列表中删除等于值的元素的第一个计数事件。
     * 计数参数以下列方式影响操作：
     * count> 0：删除等于从头到尾移动的值的元素。
     * count <0：删除等于从尾到头移动的值的元素。
     * count = 0：删除等于value的所有元素。
     *
     * @param key
     * @param num
     * @param value
     * @return
     */
    public Long removeList(String key,Integer num,String value){
        return redisTemplate.opsForList().remove(key,num,value);
    }

    //V rightPop(K key); 弹出最右边的元素，弹出之后该值在列表中将不复存在
    public Object rPopList(String key){
        Object o = redisTemplate.opsForList().rightPop(key);
        return o;
    }

    //--------------------------Hash--------------------------------



    //--------------------------Set--------------------------------

    //Long add(K key, V... values); 无序集合中添加元素，返回添加个数
    //也可以直接在add里面添加多个值 如：template.opsForSet().add("setTest","aaa","bbb")
    public Long sadd(String key, String... value){
        return redisTemplate.opsForSet().add(key, value);
    }

    //Set<V> members(K key); 返回集合中的所有成员
    public Set smembers(String key){
        return redisTemplate.opsForSet().members(key);
    }

    public Boolean sismember(String key, String value){
        return redisTemplate.opsForSet().isMember(key,value);
    }

    //V pop(K key); 移除并返回集合中的一个随机元素
    public Object spop(String key){
        return redisTemplate.opsForSet().pop(key);
    }

    public List srandMember(String key,Long num){
        return redisTemplate.opsForSet().randomMembers(key, num);
    }

    //Long remove(K key, Object... values); 移除集合中一个或多个成员
    public Long srem(String key, String... value){
        return redisTemplate.opsForSet().remove(key,value);
    }

    public Long scard(String key){
        return redisTemplate.opsForSet().size(key);
    }

    //Boolean move(K key, V value, K destKey);
    //将 member 元素从 source 集合移动到 destination 集合


    //Cursor<V> scan(K key, ScanOptions options); 遍历set


    //--------------------------ZSet--------------------------------

    // Long add(K key, Set<TypedTuple<V>> tuples);
    //新增一个有序集合

    //Boolean add(K key, V value, double score); 新增一个有序集合，存在的话为false，不存在的话为true
    public Boolean zadd(String key, String value, Double score){
        return redisTemplate.opsForZSet().add(key, value, score);
    }

    //Set<V> range(K key, long start, long end); 通过索引区间返回有序集合成指定区间内的成员，其中有序集成员按分数值递增(从小到大)顺序排列
    public Set zrange(String key, Long start, Long end){
        return redisTemplate.opsForZSet().range(key, start, end);
    }

    public Set<ZSetOperations.TypedTuple<Object>> zrangeWithScore(String key, Long start, Long end){
        return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
    }

    public Set zrevRangeWithScore(String key, Long start, Long end){
        return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);
    }

    public Set zrevRangeByScoreWithScore(String key, Long start, Long end){
        return redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, start,end);
    }

    public Double zincrBy(String key, String value, Double score){
        return redisTemplate.opsForZSet().incrementScore(key, value, score);
    }

    // Double score(K key, Object o); 获取指定成员的score值
    public Double zscore(String key, String value){
        return redisTemplate.opsForZSet().score(key, value);
    }

    public Long zcount(String key, Double start, Double end){
        return redisTemplate.opsForZSet().count(key, start, end);
    }

    //Long remove(K key, Object... values); 从有序集合中移除一个或者多个元素
    public Long zrem(String key, String... value){
        return redisTemplate.opsForZSet().remove(key, value);
    }

    public Long zsize(String key){
        return redisTemplate.opsForZSet().size(key);
    }
}
